/* Complet (Autocompletion through Graph Databases)
 *  Copyright (C) 2012  Paul Wagner, Till Speicher
 *
 *  This program is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU General Public License as published by the
 *  Free Software Foundation; either version 3 of the License, or (at your
 *  option) any later version.
 *
 *  This program is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 *  for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, see <http:/* www.gnu.org/licenses/>.
*/

/*
 * Main JS-Script for the CompletWebClient.
 * This unit handles the connections to the server through AJAX-Requests.
 *
 * @author Paul Wagner
 *
*/

//
// DOCUMENT READY
//   Some initial configurations...
//
collection = [""]; // This is the array which will contain all current suggestions

// Define our dataset
function Data () {
    this.anz_woerter = 0;
    this.wordlist = new Array();
    this.cur_word = "";
    this.map_vorschlag = new Object();  // this is the map that represents result words with relloc values (should already be in sorted order)
    this.arr_vorschlag = new Array();   // values from map will be pushed to this array as "Word (Possibility)", because we need it in this structure for output
    this.hasNoSuggestions = false;      // If request gives no results, we dont have to try it anymore for current wordset
}

// Instanciate our dataset
data = new Data();

$(document).ready(function(){

    // Bind AutoComplete-Handler to textarea
    $("#text").autocomplete({
        wordCount:1,
        mode: "inner",
        on: {
            query: function(text,cb){
                changeComplet(text, cb); // Before doing any suggestion-handling, check and perform lookup
                doManualUpdate(text, cb);
            //                var words = [];
            //                for( var i=0; i<collection.length; i++ ){
            //                    if( collection[i].toLowerCase().indexOf(text.toLowerCase()) == 0 ) words.push(collection[i]);
            //                }
            //                cb(words);
            }
        }
    });

    // Also handle clicks on primitive-Button
    $("#cprimitive").click(function(){
        data.arr_vorschlag.length = 0;
        collection.length = 0;
    });
});


//
// MAIN FUNCTION
//   This function is called when completEvent is triggered.
//   At default, this happens from within WICKs event-handling-code.
//   Its this way round, because we need first our resultset, before we can display some suggestions...
//
function changeComplet(text, cb){

    // Update Sentence
    updateSentence();

    // We just make lookups if we have at least one successor.
    // TWO POSSIBILITIES:
    //   First: We make a lookup at every onchange-event
    //   Second: We make a lookup when we have 2 chars at cur_word, retrieve maybe a bigger result list and update box
    //           If we have more than that we search our resultset for something that fits. If we have at least three items left, just update box. A new lookup at this point wouldnt improve result that much, because right word could just become 4th if not already in resultset...
    //           If not, make another lookup...
    //

    // Second possibility:
    if(data.wordlist.length > 0){
            if(!hasEnoughFittingSuggestions(5) && !data.hasNoSuggestions){
                makeLookup(text, cb);
            }
    }
}

//
// HELPER FUNCTIONS
//   Update and Lookup Stuff
//

function updateSentence(){
    // Get last sentence and split it to wordlist and current word
    var text = $('#text').val();
    text = text.replace(/\n/g," ");
    text = text.split(". ");
    if(text.length == 0){
        return;
    }

    var stnce = text[text.length-1];
    stnce = stnce.replace(/[^a-zA-ZÜÖÄüöäß ]/g, "");

//        var stnce = text[text.length-1].toLowerCase();
//
//        stnce = stnce.replace(/ß/g,"ss");
//        stnce = stnce.replace(/ü/g,"ue");
//        stnce = stnce.replace(/ä/g,"ae");
//        stnce = stnce.replace(/ö/g,"oe");
//        stnce = stnce.replace(/ß/g,"ss");
//        stnce = stnce.replace(/[^a-z ]/g, "");

    // Set WordCount
    //var all_words = text.split(" ");
    //data.anz_woerter = all_words.length;

    var words = stnce.split(" ");
    // Set last word
    var prev = data.wordlist.slice();
    if(words.length == 0){
        data.cur_word = "";
        data.wordlist.length = 0;
        return;
    }

    data.cur_word = words[words.length-1];
    
    // Set wordlist
    data.wordlist.length = 0;
    var tmp = new Array();
    var j = 0;
    for(var i = words.length-2; i >= words.length-5 && i >= 0; i--){
        tmp[j] = words[i];
        j++;
    }
    for(i = 0; i < tmp.length; i++){
        data.wordlist[i] = tmp[tmp.length-(1+i)];
    }

    if(!arrays_equal(prev, data.wordlist)){
        // If we have a new word, flush buffer
        data.arr_vorschlag.length = 0;
        data.hasNoSuggestions = false;
    }
}

function makeLookup(text, cb){
    // Make lookup and store results, update box when loading finished (do it in the callback function because of async-calls)

    // TODO: This may lead into async calls because in onchange-handler we check hasFittingSuggestion without knowing if previous call has returned yet.
    //       This might be a problem if server is slow.
    var words = "[";
    for(var i = 0; i < data.wordlist.length; i++){
        if(i != 0){
            words += ", ";
        }
        words += "\"" + data.wordlist[i] + "\"";
    }
    words += "]";

    var primitive = 'false';
    if( $('#cprimitive').attr('checked')){
        primitive = 'true';
    }
    $.post(path, {
        "json" : "{\"words\" : "+ words +", \"offset\" : \"" + data.cur_word + "\", \"primitive\" : "+ primitive +"}"
    },
    function(response){
        data.map_vorschlag = response.result;

        // Now push retrieved values to array
        data.arr_vorschlag.length = 0;
        var j = 0;
        var abs = 1;
        $.each( data.map_vorschlag, function(i, n){
            if(j == 0 && i > 0){
                abs = i;
            }
            data.arr_vorschlag[j] = n;// + "(" + (n/abs)*100 + "%)";
            j++;
        });
        if(data.arr_vorschlag.length == 0)
            data.hasNoSuggestions = true;

        // At the end, update Box
        updateBox(text, cb);

    }, "json");
}

function updateBox(text, cb){
    // Updating box is simple using JQuery. Just insert into array.
    collection.length = 0;
    for(i = 0; i < data.arr_vorschlag.length; i++){
        collection[i] = data.arr_vorschlag[i];
    }
    
    doManualUpdate(text, cb);
}

function doManualUpdate(text, cb){
    var words = [];
    for( var i=0; i<collection.length; i++ ){
        if( collection[i].toLowerCase().indexOf(text.toLowerCase()) == 0 ) words.push(collection[i]);
    }
    cb(words);
}

function hasEnoughFittingSuggestions(n){
    // Check if current word leaves at least n entries in resultset
    var cnt = 0;
    $.each(data.arr_vorschlag, function(index, value) {
        if(value.indexOf(data.cur_word) == 0){
            cnt++;
        }
    });
    if(cnt >= n){
        return true;
    }
    return false;
}

function arrays_equal(a,b) {
    return !(a<b || b<a);
}
